﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

using Axiom.Core;
using Axiom.Graphics;
using Axiom.Configuration;
using Axiom.Collections;

using Engine.GuiDANCE.Configuration;
using Engine.GuiDANCE;
using System.Reflection;

namespace Tools.Viewers.MeshViewer
{
    public static class Program
    {
        private const string CONFIG_FILE = @"ViewerConfig.xml";

        private static Root engine;
        public static MeshViewer Viewer;

        /// <summary>
        ///		Loads default resource configuration if one exists.
        /// </summary>
        private static void setup()
        {
            string resourceConfigPath = Path.GetFullPath(CONFIG_FILE);

            if (File.Exists(resourceConfigPath))
            {
                EngineConfig config = new EngineConfig();

                // load the config file
                // relative from the location of debug and releases executables
                config.ReadXml(CONFIG_FILE);

                // interrogate the available resource paths
                foreach (EngineConfig.FilePathRow row in config.FilePath)
                {
                    ResourceGroupManager.Instance.AddResourceLocation(row.src, row.type);
                }
            }
        }

        public static void Run(string fullMeshPath)
        {
            FormMeshChooser mcForm = new FormMeshChooser(fullMeshPath);
            if(mcForm.ShowDialog() == DialogResult.OK)
            {
                fullMeshPath = mcForm.MeshFileName;
                string fileName = mcForm.MeshName;
                try
                {
                    // instantiate the Root singleton
                    engine = new Root("Engine.log");


                    setup();

                    for (int index = 0; index < mcForm.ResourcePaths.Count; index++)
                    {
                        ResourceGroupManager.Instance.AddResourceLocation(mcForm.ResourcePaths[index].Path, mcForm.ResourcePaths[index].Type);
                    }

                    engine.RenderSystem = engine.RenderSystems["Direct3D9"]; //Set as DirectX
                    engine.RenderSystem.ConfigOptions["Video Mode"].Value = "1024 x 768 @ 32-bit colour";

                    FormMeshViewer form = new FormMeshViewer();
                    form.FormClosing += new FormClosingEventHandler(form_FormClosing);
                    form.RenderTypeChanged += new FormMeshViewer.RenderTypeChangedEventHandler(form_RenderTypeChanged);
                    form.BoundingBoxVisibilityChanged += new FormMeshViewer.BoundingBoxVisibilityChangedEventHandler(form_BoundingBoxVisibilityChanged);
                    form.GridsVisibilityChanged += new FormMeshViewer.GridsVisibilityChangedEventHandler(form_GridsVisibilityChanged);
                    form.Show();
                    using (Viewer = new MeshViewer(form.RenderBox, fileName))
                    {
                        Viewer.Start();
                    }
                }
                catch (Exception caughtException)
                {
                    LogManager.Instance.Write(BuildExceptionString(caughtException));
                }
            }
        }

        static void form_GridsVisibilityChanged(bool show)
        {
            Viewer.GridsVisibility = show;
        }

        static void form_BoundingBoxVisibilityChanged(bool show)
        {
            Viewer.BoundingBoxVisibility = show;
        }

        private static void form_RenderTypeChanged(MeshViewer.RenderTypes type, bool normalizeNormals)
        {
            Viewer.RenderType = type;
        }

        private static void form_FormClosing(object sender, FormClosingEventArgs e)
        {
            Viewer.Stop();
        }

        #region Main
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            string appPath = new FileInfo(System.Windows.Forms.Application.ExecutablePath).DirectoryName;
            string curPath = System.Windows.Forms.Application.StartupPath;
            Directory.SetCurrentDirectory(appPath);
            try
            {
                string fullMeshPath = null;
                if (args != null && args.Length > 0)
                {
                    fullMeshPath = args[0];
                    Console.WriteLine("Loading Mesh " + fullMeshPath);
                }
                Run(fullMeshPath);//show and start rendering
            }
            catch (Exception ex)
            {
                Console.WriteLine(BuildExceptionString(ex));
                Console.WriteLine("An exception has occurred.  Press enter to continue...");
                Console.ReadLine();
            }
        }

        private static string BuildExceptionString(Exception exception)
        {
            string errMessage = string.Empty;

            errMessage += exception.Message + Environment.NewLine + exception.StackTrace;

            while (exception.InnerException != null)
            {
                errMessage += BuildInnerExceptionString(exception.InnerException);
                exception = exception.InnerException;
            }

            return errMessage;
        }

        private static string BuildInnerExceptionString(Exception innerException)
        {
            string errMessage = string.Empty;

            errMessage += Environment.NewLine + " InnerException ";
            errMessage += Environment.NewLine + innerException.Message + Environment.NewLine + innerException.StackTrace;

            return errMessage;
        } 
        #endregion
    }
}
